<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>跨浏览器窗体消息通讯 | MyUI 4.x</title>
    <meta name="generator" content="VuePress 1.5.0">
    <link rel="icon" href="/my/favicon.ico">
    <script>
      var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?c4e5f73318b5cb0c389e3d9a05f831cc";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
      })();
    </script>
    <meta name="description" content="MyUI是美亚柏科旗下新德汇出品的Web前端一站式项目工程框架，专注于公检法行业中台系统快速搭建，框架已在多个项目实战检验。">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <link rel="preload" href="/my/assets/css/0.styles.3b7da768.css" as="style"><link rel="preload" href="/my/assets/js/app.145deadf.js" as="script"><link rel="preload" href="/my/assets/js/546.c48d7d92.js" as="script"><link rel="preload" href="/my/assets/js/1157.bac9ad26.js" as="script"><link rel="preload" href="/my/assets/js/974.ffa6c050.js" as="script">
    <link rel="stylesheet" href="/my/assets/css/0.styles.3b7da768.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/my/" class="home-link router-link-active"><img src="/my/img/logo.png" alt="MyUI 4.x" class="logo"> <span class="site-name can-hide">MyUI 4.x</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/my/guide/" class="nav-link router-link-active">
  指南
</a></div><div class="nav-item"><a href="/my/ui/components/" class="nav-link">
  组件
</a></div><div class="nav-item"><a href="/my/ui/charts/" class="nav-link">
  图表
</a></div><div class="nav-item"><a href="/my/ui/map/" class="nav-link">
  地图
</a></div><div class="nav-item"><a href="/my/ui/go/" class="nav-link">
  关系图
</a></div><div class="nav-item"><a href="/my/ui/icon/" class="nav-link">
  图标
</a></div><div class="nav-item"><a href="/my/ui/pages/" class="nav-link">
  页面
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="JSDoc" class="dropdown-title"><span class="title">JSDoc</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/my/api/components.html" class="nav-link">
  基础组件
</a></li><li class="dropdown-item"><!----> <a href="/my/api/utils.html" class="nav-link">
  工具函数
</a></li><li class="dropdown-item"><!----> <a href="/my/api/charts.html" class="nav-link">
  图表组件
</a></li><li class="dropdown-item"><!----> <a href="/my/api/map.html" class="nav-link">
  地图组件
</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/my/guide/" class="nav-link router-link-active">
  指南
</a></div><div class="nav-item"><a href="/my/ui/components/" class="nav-link">
  组件
</a></div><div class="nav-item"><a href="/my/ui/charts/" class="nav-link">
  图表
</a></div><div class="nav-item"><a href="/my/ui/map/" class="nav-link">
  地图
</a></div><div class="nav-item"><a href="/my/ui/go/" class="nav-link">
  关系图
</a></div><div class="nav-item"><a href="/my/ui/icon/" class="nav-link">
  图标
</a></div><div class="nav-item"><a href="/my/ui/pages/" class="nav-link">
  页面
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="JSDoc" class="dropdown-title"><span class="title">JSDoc</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/my/api/components.html" class="nav-link">
  基础组件
</a></li><li class="dropdown-item"><!----> <a href="/my/api/utils.html" class="nav-link">
  工具函数
</a></li><li class="dropdown-item"><!----> <a href="/my/api/charts.html" class="nav-link">
  图表组件
</a></li><li class="dropdown-item"><!----> <a href="/my/api/map.html" class="nav-link">
  地图组件
</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>开发指南</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>内置资源</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>进阶教程</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/my/guide/messager.html" aria-current="page" class="active sidebar-link">跨浏览器窗体消息通讯</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/my/guide/messager.html#需求" class="sidebar-link">需求</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/my/guide/messager.html#页面跨域消息传递" class="sidebar-link">页面跨域消息传递</a></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#页面跨浏览器窗体消息传递" class="sidebar-link">页面跨浏览器窗体消息传递</a></li></ul></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#原理" class="sidebar-link">原理</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/my/guide/messager.html#postmessage" class="sidebar-link">postMessage</a></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#localstorage" class="sidebar-link">localStorage</a></li></ul></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#bridge-桥" class="sidebar-link">Bridge 桥</a></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#实现" class="sidebar-link">实现</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/my/guide/messager.html#组成" class="sidebar-link">组成</a></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#消息传递过程" class="sidebar-link">消息传递过程</a></li></ul></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#应用" class="sidebar-link">应用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/my/guide/messager.html#页面通讯" class="sidebar-link">页面通讯</a></li><li class="sidebar-sub-header"><a href="/my/guide/messager.html#界面服务" class="sidebar-link">界面服务</a></li></ul></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>第三方类库</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="跨浏览器窗体消息通讯"><a href="#跨浏览器窗体消息通讯" class="header-anchor">#</a> 跨浏览器窗体消息通讯</h1> <h2 id="需求"><a href="#需求" class="header-anchor">#</a> 需求</h2> <h3 id="页面跨域消息传递"><a href="#页面跨域消息传递" class="header-anchor">#</a> 页面跨域消息传递</h3> <p>A页面中用<code>iframe</code>加载了B页面， 这两个页面不同源，需要双向通讯。</p> <h3 id="页面跨浏览器窗体消息传递"><a href="#页面跨浏览器窗体消息传递" class="header-anchor">#</a> 页面跨浏览器窗体消息传递</h3> <p>同一个浏览器同时打开A页面 和 B页面， 这两个页面不同源，也需要双向通讯。</p> <h2 id="原理"><a href="#原理" class="header-anchor">#</a> 原理</h2> <h3 id="postmessage"><a href="#postmessage" class="header-anchor">#</a> postMessage</h3> <p><code>postMessage</code> 可以实现不同源的页面在<code>iframe</code>中通讯， 但是不能跨浏览器窗体。</p> <h3 id="localstorage"><a href="#localstorage" class="header-anchor">#</a> localStorage</h3> <p>当 <code>localStorage</code> 存储的值发生变化时会在当前窗体window触发 storage 事件。
多个同源的页面是共享localStorage，因此浏览器同时打开多个同源页面，只要localStorage改变了，都会收到 storage 事件。</p> <h2 id="bridge-桥"><a href="#bridge-桥" class="header-anchor">#</a> Bridge 桥</h2> <p><code>postMessage</code> 可不同源通讯，但是不能跨窗体，<code>localStorage</code>可以跨窗体，但是只限同源页面。 不能满足跨窗体不同源的通讯需求。</p> <p>为了满足需求，整合<code>postMessage</code>和<code>localStorage</code>的特性，实现既能跨窗体也可以不同源的消息通讯方案，我们称这个方案叫 <code>桥</code></p> <p>就是为两个窗体或页面之间搭一座桥，把消息通过桥传递给对方。</p> <h2 id="实现"><a href="#实现" class="header-anchor">#</a> 实现</h2> <h3 id="组成"><a href="#组成" class="header-anchor">#</a> 组成</h3> <p>例如有2个相互独立应用 <code>应用A</code> 和 <code>应用B</code> 他们之间不同源的。</p> <p><img src="/my/assets/img/app1.d398c3b5.png" alt="app1"><img src="/my/assets/img/app2.03f22543.png" alt="app2"></p> <p>每个应用都自己的 <code>页面</code>、<code>Bridge</code> 和 <code>localStorage</code></p> <h3 id="消息传递过程"><a href="#消息传递过程" class="header-anchor">#</a> 消息传递过程</h3> <p><img src="/my/assets/img/messager.0c9f7e56.png" alt="messager"></p> <p>同一个浏览器同时打开 应用A的页面 和 应用B的页面，消息通信过程：</p> <ol><li><code>页面A</code>需要发信息给<code>页面B</code>，首先要知道<code>应用B</code>的桥地址（桥类库的页面url），才能搭桥（在<code>页面A</code>创建一个iframe加载<code>应用B</code>的桥页面）。
搭桥好后，通过<code>postMessage</code>把信息传递给<code>应用B</code>的 <code>桥</code>。</li> <li><code>应用B</code>的 <code>桥</code>收到消息后，把消息加上时间戳，确保了消息数据的唯一性，并写入到自己的 <code>localStorage</code>。</li> <li><code>应用B</code>的页面侦听了<code>storage</code>事件，当 <code>localStorage</code> 发生了变化，即会收到变化后的内容，即收到了<code>页面A</code>发送过来的数据。</li> <li>同理，<code>页面B</code>发送信息给<code>页面A</code>，也需要搭桥，把消息发送给 <code>应用A</code>的<code>桥</code></li> <li><code>应用A</code>的 <code>桥</code>收到消息后，并写入到自己的 <code>localStorage</code>。</li> <li><code>应用A</code>的页面侦听了<code>storage</code>事件，当 <code>localStorage</code> 发生了变化, 即收到了<code>页面B</code>发送过来的数据。</li></ol> <h2 id="应用"><a href="#应用" class="header-anchor">#</a> 应用</h2> <h3 id="页面通讯"><a href="#页面通讯" class="header-anchor">#</a> 页面通讯</h3> <p>两个互相独立的页面通讯，可以是<code>iframe</code>嵌套或浏览器新窗口</p> <!----><h3 id="界面服务"><a href="#界面服务" class="header-anchor">#</a> 界面服务</h3> <p>界面服务是指，A页面提供了某种服务能力，B页面需要使用A页面的服务得到某些结果，B页面可以对A页面发起服务调用。类似API的调用。</p> <!----></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/my/guide/vars.html" class="prev">
        主题变量
      </a></span> <span class="next"><a href="/my/guide/axios.html">
        Axios
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/my/assets/js/app.145deadf.js" defer></script><script src="/my/assets/js/546.c48d7d92.js" defer></script><script src="/my/assets/js/1157.bac9ad26.js" defer></script><script src="/my/assets/js/974.ffa6c050.js" defer></script>
  </body>
</html>
